﻿/*******************************************************
 * 
 * 作者：胡庆访
 * 创建时间：20100322
 * 说明：配置服务的提供程序
 * 版本号：1.0.0
 * 
 * 历史记录：
 * 创建文件 胡庆访 20100322
 * 添加数据库名的配置 胡庆访 20100323
 * 
*******************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.SqlClient;

namespace OpenExpressApp
{
    /// <summary>
    /// 一个可以存储的配置
    /// </summary>
    public interface ISavableConfig
    {
        /// <summary>
        /// 保存到配置中
        /// </summary>
        /// <returns></returns>
        bool Save();
    }

    /// <summary>
    /// 连接字符串的配置
    /// </summary>
    public interface IConnctionStringConfig : ISavableConfig
    {
        /// <summary>
        /// 是否启用了单机版。
        /// </summary>
        bool RunAtLocal { get; }

        /// <summary>
        /// 指标库库名
        /// </summary>
        string DBName_GIX4 { get; set; }

        /// <summary>
        /// 估算库库名
        /// </summary>
        string DBName_Estimate { get; set; }

        /// <summary>
        /// 服务器地址
        /// </summary>
        string DB_Server { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        string DB_UserID { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        string DB_Password { get; set; }
    }

    /// <summary>
    /// 配置类
    /// </summary>
    public class AppConfig : IConnctionStringConfig, ISavableConfig
    {
        /// <summary>
        /// SingelTon
        /// </summary>
        public static readonly AppConfig Instance;

        static AppConfig()
        {
            Instance = new AppConfig();
        }

        /// <summary>
        /// 本类最终是对这个字段的内容进行修改
        /// </summary>
        private Configuration _innerConfig;

        private AppConfig()
        {
            this.ReadConfig();
        }

        /// <summary>
        /// 远程服务器地址
        /// </summary>
        public Uri RemoteServerAddress
        {
            get
            {
                var clientSection = this._innerConfig.GetSection("system.serviceModel/client") as System.ServiceModel.Configuration.ClientSection;
                return clientSection.Endpoints[0].Address;
            }
            set
            {
                string section = "system.serviceModel/client";
                var clientSection = this._innerConfig.GetSection(section) as System.ServiceModel.Configuration.ClientSection;
                try
                {
                    clientSection.Endpoints[0].Address = value;
                }
                catch (Exception ex)
                {
                    throw new Exception("链接地址格式出错。", ex);
                }
            }
        }

        public string LoginName
        {
            get
            {
                return _innerConfig.AppSettings.Settings["LoginName"].Value;
            }
            set
            {
                this._innerConfig.AppSettings.Settings["LoginName"].Value = value;
            }
        }

        public double ZoomScale
        {
            get
            {
                return double.Parse(_innerConfig.AppSettings.Settings["ZoomScale"].Value);
            }
            set
            {
                this._innerConfig.AppSettings.Settings["ZoomScale"].Value = value.ToString();
            }
        }
        

        #region IConnctionStringConfig Members

        /// <summary>
        /// 连接字符串模板
        /// </summary>
        private static readonly string CONNECTION_FORMAT = @"Data Source=192.168.0.128\SQLExpress;Initial Catalog=OpenExpressApp;User ID=GIX4;Password=GIX4";

        /// <summary>
        /// 指标库的连接字符串名
        /// </summary>
        private static readonly string CONNECTION_STRING_NAME_GIX4 = "BusinessDBName";

        /// <summary>
        /// 估算库的连接字符串名
        /// </summary>
        private static readonly string CONNECTION_STRING_NAME_ESTIMATE = "EstimateDBName";

        /// <summary>
        /// Key: Setting Name
        /// Value: DataBase Name
        /// </summary>
        private static readonly Dictionary<string, string> CONNECTION_STRING_MAPPINGS = new Dictionary<string, string>()
        {
            {"OpenExpressApp","OpenExpressApp"},
            {CONNECTION_STRING_NAME_GIX4,"GIX4"},
            {CONNECTION_STRING_NAME_ESTIMATE,"Estimate"},
            {"BQNormDBName","BQNorm_GIX4"},
        };

        /// <summary>
        /// 临时存储连接字符串的值
        /// </summary>
        private SqlConnectionStringBuilder _connectionString;

        public bool RunAtLocal
        {
            get
            {
                string value = this._innerConfig.AppSettings.Settings["CslaDataPortalProxy"].Value;
                return string.IsNullOrEmpty(value);
            }
            set
            {
                this._innerConfig.AppSettings.Settings["CslaDataPortalProxy"].Value = value ?
                    string.Empty : "OpenExpressApp.Host.WPF.DogWCFProxy, OpenExpressApp.Host.WPF";
            }
        }

        public string DBName_GIX4 { get; set; }

        public string DBName_Estimate { get; set; }

        public string DB_Server
        {
            get
            {
                return this._connectionString.DataSource;
            }
            set
            {
                this._connectionString.DataSource = value;
            }
        }

        public string DB_UserID
        {
            get
            {
                return this._connectionString.UserID;
            }
            set
            {
                this._connectionString.UserID = value;
            }
        }

        public string DB_Password
        {
            get
            {
                return this._connectionString.Password;
            }
            set
            {
                this._connectionString.Password = value;
            }
        }

        private void ReadConnectionSettings()
        {
            var conStrings = this._innerConfig.ConnectionStrings.ConnectionStrings
                .Cast<ConnectionStringSettings>().ToArray();

            //读取GIX4数据库配置
            var settings = conStrings.FirstOrDefault(s => s.Name == CONNECTION_STRING_NAME_GIX4);
            if (settings != null)
            {
                this._connectionString = new SqlConnectionStringBuilder(settings.ConnectionString);
                this.DBName_GIX4 = this._connectionString.InitialCatalog;
            }
            else
            {
                this.DBName_GIX4 = CONNECTION_STRING_MAPPINGS[CONNECTION_STRING_NAME_GIX4];
            }

            //读取估算库数据库配置
            settings = conStrings.FirstOrDefault(s => s.Name == CONNECTION_STRING_NAME_ESTIMATE);
            if (settings != null)
            {
                this._connectionString = new SqlConnectionStringBuilder(settings.ConnectionString);
                this.DBName_Estimate = this._connectionString.InitialCatalog;
            }
            else
            {
                this.DBName_Estimate = CONNECTION_STRING_MAPPINGS[CONNECTION_STRING_NAME_ESTIMATE];
            }

            //读取通用的连接字符串
            if (this._connectionString == null)
            {
                var names = CONNECTION_STRING_MAPPINGS.Keys;
                settings = conStrings.FirstOrDefault(s => names.Contains(s.Name));
                if (settings != null)
                {
                    this._connectionString = new SqlConnectionStringBuilder(settings.ConnectionString);
                }
                else
                {
                    this._connectionString = new SqlConnectionStringBuilder(CONNECTION_FORMAT);
                }
            }
        }

        private void SaveConnectionSettings()
        {
            var conListSettings = this._innerConfig.ConnectionStrings.ConnectionStrings;
            var conStrings = conListSettings.Cast<ConnectionStringSettings>().ToArray();

            if (this.RunAtLocal)
            {
                //连接字符串的值是使用在_connectionString字段中，需要在存储前先把这些值写入到_innerConfig中。
                foreach (var kv in CONNECTION_STRING_MAPPINGS)
                {
                    var settingName = kv.Key;
                    var dbName = kv.Value;

                    var settings = conStrings.FirstOrDefault(s => s.Name == settingName);

                    //如果不存在，则先加入里面。
                    if (settings == null)
                    {
                        settings = new ConnectionStringSettings(settingName, CONNECTION_FORMAT);
                        this._innerConfig.ConnectionStrings.ConnectionStrings.Add(settings);
                    }

                    var connectionString = new SqlConnectionStringBuilder(settings.ConnectionString);
                    connectionString.DataSource = this._connectionString.DataSource;
                    connectionString.UserID = this._connectionString.UserID;
                    connectionString.Password = this._connectionString.Password;

                    if (settings.Name == CONNECTION_STRING_NAME_GIX4)
                    {
                        connectionString.InitialCatalog = this.DBName_GIX4;
                    }
                    else if (settings.Name == CONNECTION_STRING_NAME_ESTIMATE)
                    {
                        connectionString.InitialCatalog = this.DBName_Estimate;
                    }
                    else
                    {
                        connectionString.InitialCatalog = dbName;
                    }

                    settings.ConnectionString = connectionString.ToString();
                }
            }
            else
            {
                foreach (var kv in CONNECTION_STRING_MAPPINGS)
                {
                    var settingName = kv.Key;
                    var settings = conStrings.FirstOrDefault(s => s.Name == settingName);
                    if (settings != null)
                    {
                        conListSettings.Remove(settings);
                    }
                }
            }
        }

        #endregion

        /// <summary>
        /// 保存
        /// </summary>
        public bool Save()
        {
            try
            {
                this.SaveConfig();
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 读取配置信息到内存中
        /// </summary>
        private void ReadConfig()
        {
            this._innerConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            this.ReadConnectionSettings();
        }

        /// <summary>
        /// 把内存中的值，存储到配置文件中
        /// </summary>
        private void SaveConfig()
        {
            this.SaveConnectionSettings();

            this._innerConfig.Save();

            //刷新配置文件
            ConfigurationManager.RefreshSection("appSettings");
            ConfigurationManager.RefreshSection("connectionStrings");
            ConfigurationManager.RefreshSection("system.serviceModel/client");
        }
    }
}
